/*
 * Copyright (c) 2013 XDream
 * Copyright (c) 2013 bruceshu <shuhuan.bruce@gmail.com>
 * 2024-9-20
 */

#include "ffmpeg_video_decoder.h"

namespace mydecoder {

FfmpegVideoDecoder::FfmpegVideoDecoder(/* args */)
    : m_codecCtx(nullptr)
{
}

FfmpegVideoDecoder::~FfmpegVideoDecoder()
{
}

VideoCodecError FfmpegVideoDecoder::init(const AVBuffer *buffer)
{
    m_codecCtx = avcodec_alloc_context3(nullptr);

    m_codecCtx->codec_type = AVMEDIA_TYPE_VIDEO;
    m_codecCtx->thread_count = 1;
    m_codecCtx->thread_type = FF_THREAD_SLICE;
    m_codecCtx->time_base = {1, 1000};

    // todo：根据传进来的参数，配置编码格式
    m_codecCtx->codec_id = AV_CODEC_ID_H264;
    
    const AVCodec *codec = nullptr;
    // todo：根据编码器名字，寻找解码器,找不到就用编码器id找编码器
    // if () {
    //     codec = avcodec_find_decoder_by_name("");
    // } else {
        codec = avcodec_find_decoder(m_codecCtx->codec_id);
    // }
    
    if (codec == nullptr) {
        // print();
        return CodecErrorInit;
    }

    // 获取配置参数
    std::string useCpuNumForThreads = getOption("use-cpu-num-for-threads");
    AVDictionary *opts = nullptr;
    int ret = 0;
    if (useCpuNumForThreads != "") {
        av_dict_set(&opts, "use-cpu-num-for-threads", useCpuNumForThreads.c_str(), 0);
    }
    
    ret = avcodec_open2(m_codecCtx, codec, &opts);
    if (ret < 0) {
        return CodecError;
    }

    av_dict_free(&opts);

    return CodecErrorNone;
}

void FfmpegVideoDecoder::flush()
{
    if (m_codecCtx != nullptr) {
        avcodec_flush_buffers(m_codecCtx);
    }
}

VideoCodecError FfmpegVideoDecoder::decode()
{
    if (m_codecCtx == nullptr || m_videoDecodedCallback == nullptr) {
        return CodecErrorParam;
    }

    AVFrame *frame = av_frame_alloc();
    int ret = 0;

    ret = avcodec_receive_frame(m_codecCtx, frame);
    if (ret >= 0) {
        m_videoDecodedCallback->onDecodedFrame(frame);
    }

    // avcodec_send_packet(m_codecCtx, packet);
    return CodecErrorNone;
}

}
